延續上文關於JavaScript基本型別的內容,這篇主要講解字串(string)、布林值(boolean)、null、undefined和Symbol(ES6新增)。
字串就是文字。例如是'Hello World'、'JavaScript基本功修煉'、'12345'等等。12345雖然本來是數字,但放在引號''裏就會成為了字串。
我們可以單引號''、雙引號""、重音符``把字串括著:
//單引號
var singleQuote = 'JavaScript好難!'
//雙引號
var doubleQuote = "JavaScript好難!"
//重音符
var backtick = `JavaScript好難!`
注意,這些引號都不能混合使用,例如'12345",這樣做會報錯。
剛學JS幾星期後,我開始轉用重音符的寫法,因為它比較方便寫和閱讀,至此人生又少了點坎坷。
具體的好處:
var fruit = `Fruit:
1. apple
2. orange
3. cherry
4. banana
`
單或雙引號就不能斷行,這樣會報錯:
var fruit = "Fruit:
1. apple
2. orange
3. cherry
4. banana
"
console.log(fruit); //Uncaught SyntaxError: Invalid or unexpected token
${}
var discount = 0.7
var fries = 15
console.log(`今天薯條的售價是${fries * discount}元`);
你可能會認為這個簡單例子其實用單或雙引號也可以,就像這樣:
console.log('今天薯條的售價是' + fries * discount + '元')
這個寫法也行的。但是,如果今天的情況是要組合一大堆字串,而非單單一句,那麼我們在輸入和組合字串的時候,就要很耗時地去找出哪裏要分開,哪裏要加上引號和加號。例如我們要組合一個HTML字串時:
用${}去寫:
//計算打折後的價錢
function discount(oldPrice){
return oldPrice * 0.7
}
var price1 = `
<h2>今天的特價貨品:</h2>
<ul>
<li>薯片:$${discount(20)},原價$20</li>
<li>漢堡:$${discount(30)},原價$30</li>
</ul>
`
用''或""去寫:
var price2 =
'<h2>今天的特價貨品:</h2>' + '<ul><li>薯片:$' + discount(20) + ',原價$20</li><li>漢堡:$' + discount(30) + ',原價$30</li></ul>'
雖然回傳的結果是一樣(只差在是逼在一行還是整齊地斷行),但用``去寫,除了不用去想哪裏要下+和'',也可以像寫HTML一樣去寫,寫法一目了然!
使用特別文字的情況的例子:
剛才提及單或雙引號是不能斷行,但如果加上跳脫符號\n或者\,也是可以實現的。
var fruit1 = 'Fruit:\n1. apple\n2. orange\n3. cherry\n4. banana'
這樣寫的話,console會以斷行顯示。
var fruit3 = 'Fruit: \
1. apple \
2. orange \
3. cherry \
4. banana'
注意,\後面不能輸入空白或其他字元。
然而這個寫法在console顯示回傳時仍是以一行顯示,並沒有斷行。所以這個寫法只是讓你在寫程式碼時,合法地在單引號或雙引號裏按enter去斷行。
其實這些字串被渲染到網頁上時,一併都是以一行顯示,所以這個微小的分別只是在查console時會碰到。
其他運用例子:
當字串裏包含了單引號,就不能用單引號去包著字串。我們可以轉用雙引號或加入\作分隔。
console.log('Tom's car') //報錯
console.log("Tom's car")
console.log('Tom\'s car')
console.log('\u00AE') //®
console.log('\u{1F606}') // ?
布林值就是true和false,非常簡單。
5 == 7 //false
undefined === null //false
2 > 1 //true
通常布林值會配搭邏輯運算子||(or)、&&(and)、!(not)使用。之後的文章會談到。
falsy和truthy兩大類。false,它就是屬於falsy類別,相反,true就是屬於truthy類別。Boolean(value)去把值轉型為布林值。false (falsy):0,null,undefined,NaN,""
true(truthy):
除了以上的值都是。
以下的例子要格外注意:
Boolean('0') //true。'0'是一個字串,只要不是空字串就會回傳true
Boolean('') //false
Boolean(' ') //true。這不是一個空字串,所以回傳true
null = 「沒有值」的值undefined = 沒有被賦予任何值(不論有沒有宣告變數)
undefined。但JavaScript不會自動賦予null給變數,那必然是由你自己動手去賦予。null和undefined都是falsy
null的型別是object,但undefined的型別是undefined
null == undefined //true,因為它們都是falsy。null === undefined //false。嚴謹模式會比較兩者的型別。null是object,但undefined是undefined。ES6新增了Symbol這個基本型別。根據MDN的解釋,它雖然也有其他用法,但最主要是用在物件裏的屬性。
A symbol value may be used as an identifier for object properties; this is the data type's primary purpose
x和y都是Symbol(),它們卻不相等。const x = Symbol();
const y = Symbol();
console.log(x === y) //false
``或""。用Symbol時一定要寫成Symbol()
Symbol()後面的那個()只是用作寫下一些關於這個Symbol的描述,並沒有實際作用。例如:Symbol("person")、Symbol("age")。方便我們看到多個Symbol()時,可以一眼看出()裏的描述,幫助自己更快區分到它們,也有助於除錯。Symbol()其中一個優勢是它並不明顯,第三方不能用某些語法去查詢到這個屬性,例如Object.keys(user):
const id = Symbol("id")
let user = {
name: 'Tom',
age: 23,
birthday: 'Aug 11',
id: 111,
[id]: 222
}
console.log(Object.keys(user)) //["name", "age", "birthday", "id"]
for...in:
for (let key in user) console.log(key);
// name
// age
// birthday
// id
然而,Object.assgin()卻可以查看到,因為這個語法原意是把所有屬性都複製起來,而Symbol()也會被複製到。此外,Object.getOwnPropertySymbols()也能針對找出Symbol()屬性。
避免因為鍵值相同,使較新的屬性覆蓋掉較舊的屬性。
let user = {
name: 'Tom',
age: 23,
birthday: 'Aug 11',
id: 111
}
//覆蓋掉user的本身的id
user.id = 222;
以上這個例子可以想像成user這個物件是來自第三方的程式碼,裏面雖然也有id這個屬性,但我這邊也想建立一個id的屬性作為其他用途,可是又不能蓋掉之前的id,所以這個例子可以用Symbol():
let user = {
name: 'Tom',
age: 23,
birthday: 'Aug 11',
id: 111
}
//確保不會蓋掉之前的屬性
const id = Symbol("id")
user[id] = 222

更直接的寫法:
const id = Symbol("id")
let user = {
name: 'Tom',
age: 23,
birthday: 'Aug 11',
id: 111,
[id]: 222
}
注意,鍵值需要用[]包起來,沒有用[]的話,鍵值會變成字串型別,直接蓋掉了原本的id。
倒過來想,如果我們想避免自己建立的屬性被第三方開發者蓋掉,我們也可以自己用Symbol()去建立屬性。此外,使用Symbol()也能避免第三方輕易查看到該屬性。
雖然Symbol的主要賣點是獨特的存在,但如果我們想在程式碼某個地方,再次使用同一個Symbol值,就可以用Symbol.for()的方法。
Symbol.for()可以把當在()裏的字串當作是參數,例如執行Symbol.for("cat")時,JavaScript會查看有沒有"cat"作為參數的Symbol值,如果有,就返回這個值,如沒有,就去建立一個,把它注冊成為全域的Symbol。
以下的例子可見,id和idAgain是指向同一個Symbol值:
let id = Symbol.for("id");
let idAgain = Symbol.for("id");
console.log(id === idAgain) //true
如果我調用Symbol("id")和Symbol.for("id")各30次,Symbol("id")會返回30個不同的Symbol值,但Symbol.for("id")30次都是返回同一個Symbol值。
字串:
''、""、``括住''和""包字串時不能斷行``,連接字串時使用${},這樣較方便和易讀布林值:
true和false
0,null,undefined,NaN,""是falsy,其餘都是truthy
Boolean()去把值轉為布林值null、undefined:
null是「沒有值」的值,undefined是指沒有被賦予任何值null和undefined都是falsy
null的型別是object,但undefined的型別是undefined
Symbol():
Symbol()是獨一無二的Symbol()主要用途是避免蓋掉物件裏的其他屬性Symbol()的屬性較隱蔽,但不代表不能被查詢Symbol.for()返回同一個symbol值JAVASCRIPT.INFO - String
JAVASCRIPT.INFO - Data Types
undefined 和 null 的差別
Symbol:
JAVASCRIPT.INFO - Symbol
ECMAScript 6 入门
The Complete Guide to JS Symbols ES6